home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
et
/
et3_0-a1.lha
/
et3
/
src
/
Env.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-06-18
|
8KB
|
430 lines
#ifdef __GNUG__
#pragma implementation
#endif
#include "Env.h"
#include "Class.h"
#include "String.h"
#include "System.h"
#include "OrdColl.h"
#include "StreamBuf.h"
#include "CLib.h"
//---- EnvParser ---------------------------------------------------------------
class EnvParser {
FILE *ifp;
public:
EnvParser(FILE *f)
{ ifp= f; }
virtual void KeyValue(char*, char*, char*)
{ }
virtual void Char(int)
{ }
void Parse();
};
void EnvParser::Parse()
{
char name[200], type[200], value[200];
int c, state= 0, ni, ti, vi;
ni= ti= vi= 0;
while ((c= fgetc(ifp)) != EOF) {
if (c == '\n') {
state= 0;
if (ni > 0) {
name[ni++]= 0;
type[ti++]= 0;
value[vi++]= 0;
ni= ti= vi= 0;
KeyValue(name, value, type);
}
Char(c);
continue;
}
switch (state) {
case 0: // start of line
switch (c) {
case ' ':
case '\t':
break;
case '#':
state= 1;
break;
default:
state= 2;
break;
}
break;
case 1: // comment
break;
case 2: // name
switch (c) {
case ' ':
case '\t':
case ':':
state= 3;
break;
case '(':
state= 7;
break;
default:
break;
}
break;
case 3: // ws before value
if (c != ' ' && c != '\t')
state= 4;
break;
case 4: // value
break;
case 5: // type
if (c == ')')
state= 6;
break;
case 6: // optional ':'
state= (c == ':') ? 3 : 4;
break;
case 7:
state= (c == ')') ? 6 : 5;
break;
}
switch (state) {
case 2:
name[ni++]= c;
break;
case 4:
value[vi++]= c;
break;
case 5:
type[ti++]= c;
break;
}
if (state != 4)
Char(c);
}
}
//---- ReadEnvParser -----------------------------------------------------------
class ReadEnvParser: public EnvParser {
EnvLevel level;
public:
ReadEnvParser(FILE *f, EnvLevel l) : EnvParser(f)
{ level= l; }
void KeyValue(char *name, char *value, char *type)
{ Env::SetValue(name, value, level, type); }
};
//---- WriteEnvParser ----------------------------------------------------------
class WriteEnvParser: public EnvParser {
FILE *ofp;
public:
WriteEnvParser(FILE *f, FILE *of) : EnvParser(f)
{ ofp= of; }
void KeyValue(char *name, char *value, char *type);
void Char(int c)
{ fputc(c, ofp); }
};
void WriteEnvParser::KeyValue(char *name, char *value, char*)
{
EnvRec *er= Env::Lookup(name);
if (er && er->changed) {
er->changed= FALSE;
if (er->op)
er->Write(er->op);
if (er->op2)
er->Write2(er->op);
fprintf(ofp, "%s", er->value);
} else
fprintf(ofp, "%s", value);
}
//---- EnvRec ------------------------------------------------------------------
NewMetaImpl(EnvRec,Object, (T(name), TS(value), TS(type), TE(level), TB(changed)));
EnvRec::EnvRec(Symbol n, char *v, char *t, EnvLevel l)
{
name= n;
value= strsave(v);
level= l;
if (t)
type= strsave(t);
else
type= 0;
changed= (l == eEnvChange);
op= 0;
}
EnvRec::~EnvRec()
{
SafeDelete(value);
SafeDelete(type);
}
void EnvRec::Read(Object *op)
{
IStream is(strlen(value), value);
op->ReadFrom(is);
}
Object *EnvRec::Read2()
{
Object *op= 0;
IStream is(strlen(value), value);
is >> op;
return op;
}
void EnvRec::Write(Object *op)
{
char *cp= new char[1000];
OStream os(1000, cp);
op->PrintOn(os);
ChangeValue(cp, 0, eEnvChange);
delete cp;
}
void EnvRec::Write2(Object*)
{
}
void EnvRec::ChangeValue(char *v, char*, EnvLevel l)
{
if (l != eEnvChange && level == l) {
fprintf(stderr,
"EnvRec::ChangeValue: duplicate entry <%s=%s> for level %d; ignored\n",
name.AsString(), v, l);
return;
}
if (strcmp(value, v) != 0) {
if (l == eEnvChange)
changed= TRUE;
else {
changed= FALSE;
level= l;
}
strreplace(&value, v);
if (changed && op)
Read(op);
}
}
void EnvRec::InspectorId(char *buf, int bufSize)
{
strn0cpy(buf, name.AsString(), bufSize);
}
int EnvRec::Compare(Object *op)
{
return StrCmp((byte*)name.AsString(),
(byte*)Guard(op,EnvRec)->name.AsString(), -1, sortmap);
}
//---- EnvRec ------------------------------------------------------------------
NewMetaImpl(Env,Object, (TP(table), TB(terminated)));
static Env gEnv;
OrdCollection *Env::table;
bool Env::terminated;
Env::Env()
{
}
Env::~Env()
{
terminated= TRUE;
if (table) {
table->FreeAll();
SafeDelete(table);
}
}
void Env::Init()
{
if (table)
return;
table= new OrdCollection;
ReadFile(form("%s/ETRC", gEtDir), eEnvGlobal);
ReadFile(form("%s/ETRC", gSystem->HomeDirectory()), eEnvUser);
ReadFile("ETRC", eEnvLocal);
for (int i= 0; CLib::Environ[i]; i++)
SetValue(CLib::Environ[i], eEnvEnvironment);
}
EnvRec *Env::Lookup(char *n)
{
if (table == 0)
Env::Init();
u_int name;
if (name= SymbolTable::Lookup(n)) {
Iter next(table);
EnvRec *er;
while (er= (EnvRec*) next())
if (er->name.Id() == name)
return er;
}
return 0;
}
//---- Loading/Storing ---------------------------------------------------------
void Env::ReadFile(char *fname, EnvLevel level)
{
FILE *ifp;
if (ifp= fopen(fname, "r")) {
ReadEnvParser rp(ifp, level);
rp.Parse();
fclose(ifp);
}
}
void Env::Save()
{
FILE *ifp, *ofp;
if (ofp= fopen(form("%s/ETRC.new", gSystem->HomeDirectory()), "w")) {
if (ifp= fopen(form("%s/ETRC", gSystem->HomeDirectory()), "r")) {
WriteEnvParser wp(ifp, ofp);
wp.Parse();
Iter next(table);
EnvRec *er;
while (er= (EnvRec*) next())
if (er->changed) {
er->changed= FALSE;
fprintf(ofp, "%s %s\n", er->name.AsString(), er->value);
}
fclose(ifp);
fclose(ofp);
gSystem->Rename(form("%s/ETRC", gSystem->HomeDirectory()),
form("%s/ETRC.BAK", gSystem->HomeDirectory()));
gSystem->Rename(form("%s/ETRC.new", gSystem->HomeDirectory()),
form("%s/ETRC", gSystem->HomeDirectory()));
return;
}
fclose(ofp);
}
}
//---- GetValue ----------------------------------------------------------------
char *Env::getvalue(char *name)
{
if (terminated)
return 0;
EnvRec *er= Lookup(form("%s.%s", gProgname, name));
if (er == 0)
er= Lookup(form("*.%s", name));
if (er == 0)
er= Lookup(name);
if (er == 0)
return 0;
return er->value;
}
int Env::GetValue(char *name, int dflt)
{
char *cp= Env::getvalue(name);
if (cp) {
int n;
if (sscanf(cp, "%d", &n) == 1)
return n;
if (strcmp(cp, "TRUE") == 0 || strcmp(cp, "ON") == 0
|| strcmp(cp, "YES") == 0)
return 1;
if (strcmp(cp, "FALSE") == 0 || strcmp(cp, "OFF") == 0
|| strcmp(cp, "NO") == 0)
return FALSE;
}
return dflt;
}
char *Env::GetValue(char *name, char *dflt)
{
char *cp= Env::getvalue(name);
if (cp)
return cp;
return dflt;
}
//---- SetValue ----------------------------------------------------------------
void Env::SetValue(char *name, char *value, EnvLevel level, char *type)
{
if (table == 0)
Env::Init();
EnvRec *er= Lookup(name);
if (er)
er->ChangeValue(value, type, level);
else
table->Add(new EnvRec(name, value, type, level));
}
void Env::SetValue(char *name, EnvLevel level)
{
char *buf= strsave(name), *cp;
if (cp= strchr(buf, '=')) {
*cp++= 0;
SetValue(buf, cp, level);
} else
SetValue(name, "1", level);
delete buf;
}
void Env::SetValue(char *name, int value)
{
SetValue(name, form("%d", value));
}
void Env::SetValue(char *name, double value)
{
SetValue(name, form("%f", value));
}
void Env::SetBoolValue(char *name, bool value)
{
SetValue(name, value ? "TRUE" : "FALSE");
}
//---- Bind --------------------------------------------------------------------
bool Env::Bind(Object *&op, char *name)
{
EnvRec *er= Lookup(form("%s.%s", gProgname, name));
if (er == 0)
er= Lookup(form("*.%s", name));
if (er == 0)
er= Lookup(name);
if (er) {
er->op= op;
er->Read(op);
return TRUE;
}
return FALSE;
}